'/
' GUI Library
' Written by Anton Berlin, 2010.
' 
' =========================================================================
' 
' This program is free software; you can redistribute it and/or modify
' it under the terms of the GNU Lesser General Public License as published
' by the Free Software Foundation; either version 3 of the License.
' 
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY; without even the implied warranty of
' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
' GNU General Public License for more details.
' 
' You should have received a copy of the GNU Lesser General Public License
' along with this program; if not, write to the Free Software
' Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
'/

superstrict

import BRL.LinkedList
import BRL.PolledInput
import BRL.GLMax2D
import BRL.FreeTypeFont
import Pub.Glew

import "GUI_InputThread.bmx"

import "../drawutil/drawutil.bmx"

type GUI_Gadget

	'// -------------------------------------------------------------------------------------------------------------
	'// Force all gadgets to have a draw method. This is called to draw the gadget.
	'// -------------------------------------------------------------------------------------------------------------
	method draw() abstract;
	
	'// -------------------------------------------------------------------------------------------------------------
	'// Force all gadgets to have a design method. This draws the application specific design of the gadget. This
	'// method is explicitly written by the user of this library.
	'// -------------------------------------------------------------------------------------------------------------
	method design() abstract;
	
	'// -------------------------------------------------------------------------------------------------------------
	'// Move the gadget around.
	'// -------------------------------------------------------------------------------------------------------------
	method move(x:double, y:double)
	
		m_posX = x;
		m_posY = y;
	
	end method
	
	'// -------------------------------------------------------------------------------------------------------------
	'// Return the keyboard input of this gadget, if possible.
	'// -------------------------------------------------------------------------------------------------------------
	method getInput:string()
	
		if (m_input) ..
			return m_input;
		
		return null;
	
	end method
	
	'// -------------------------------------------------------------------------------------------------------------
	'// Set the visibility of the layer.
	'// -------------------------------------------------------------------------------------------------------------
	method setVisibility(visible:byte)
	
		m_visible = visible;
	
	end method
	
	'// -------------------------------------------------------------------------------------------------------------
	'// Set the gadget position.
	'// -------------------------------------------------------------------------------------------------------------
	method setPos(x:double, y:double)
	
		m_posX = x;
		m_posY = y;
	
	end method
	
	'// -------------------------------------------------------------------------------------------------------------
	'// Set the gadget dimension (width and height).
	'// -------------------------------------------------------------------------------------------------------------
	method setDimensions(width:double, height:double)
	
		m_width = width;
		m_height = height;
	
	end method
	
	'// -------------------------------------------------------------------------------------------------------------
	'// Set the transparency of this gadget.
	'// -------------------------------------------------------------------------------------------------------------
	method setTransparency(alpha:double)
	
		m_transparency = alpha;
	
	end method
	
	'// -------------------------------------------------------------------------------------------------------------
	'// Set the primitive color.
	'// -------------------------------------------------------------------------------------------------------------
	method setPrimitiveColor(r:byte, g:byte, b:byte)
	
		m_primitiveR = r;
		m_primitiveG = g;
		m_primitiveB = b;
	
	end method
	
	'// -------------------------------------------------------------------------------------------------------------
	'// Set whether or not to use a shadow for the gadget.
	'// -------------------------------------------------------------------------------------------------------------
	method setSurroundingShadowUsage(value:byte)
	
		m_useSurroundingShadows = value;
	
	end method
	
	'// -------------------------------------------------------------------------------------------------------------
	'// Set what object this gadget should be hooked to.
	'// -------------------------------------------------------------------------------------------------------------
	method setHookedObject(objName:string)
	
		m_hookedObject = objName;
	
	end method
	
	'// -------------------------------------------------------------------------------------------------------------
	'// Set what method this gadget should invoke when executed.
	'// -------------------------------------------------------------------------------------------------------------
	method setMethodHook(methodName:string)
	
		m_methodHook = methodName;
	
	end method
	
	'// -------------------------------------------------------------------------------------------------------------
	'// Function for drawing a shadow around the gadget.
	'// -------------------------------------------------------------------------------------------------------------
	method drawSurroundingShadow()
	
		local sx:int = m_posX;
		local sy:int = m_posY;
		local ex:int = m_posX + m_width;
		local ey:int = m_posY + m_height;
		
		setColor(0, 0, 0);
		
		if (m_useSurroundingShadows = 1) then
		
			setAlpha(m_transparency * 0.05);
			drawLine(sx - 6, sy - 6, sx - 6, ey + 5, false); '// Left
			drawLine(ex + 5, sy - 6, ex + 5, ey + 5, false); '// Right
			drawLine(sx - 5, sy - 6, ex + 5, sy - 6, false); '// Upper
			drawLine(sx - 6, ey + 5, ex + 6, ey + 5, false); '// Lower
			setAlpha(m_transparency * 0.10);
			drawLine(sx - 5, sy - 5, sx - 5, ey + 4, false);
			drawLine(ex + 4, sy - 5, ex + 4, ey + 4, false);
			drawLine(sx - 4, sy - 5, ex + 4, sy - 5, false);
			drawLine(sx - 5, ey + 4, ex + 5, ey + 4, false);
			setAlpha(m_transparency * 0.20);
			drawLine(sx - 4, sy - 4, sx - 4, ey + 3, false);
			drawLine(ex + 3, sy - 4, ex + 3, ey + 3, false);
			drawLine(sx - 3, sy - 4, ex + 3, sy - 4, false);
			drawLine(sx - 4, ey + 3, ex + 4, ey + 3, false);
			setAlpha(m_transparency * 0.30);
			drawLine(sx - 3, sy - 3, sx - 3, ey + 2, false);
			drawLine(ex + 2, sy - 3, ex + 2, ey + 2, false);
			drawLine(sx - 2, sy - 3, ex + 2, sy - 3, false);
			drawLine(sx - 3, ey + 2, ex + 3, ey + 2, false);
			setAlpha(m_transparency * 0.50);
			drawLine(sx - 2, sy - 2, sx - 2, ey + 1, false);
			drawLine(ex + 1, sy - 2, ex + 1, ey + 1, false);
			drawLine(sx - 1, sy - 2, ex + 1, sy - 2, false);
			drawLine(sx - 2, ey + 1, ex + 2, ey + 1, false);
			setAlpha(m_transparency * 0.75);
			drawLine(sx - 1, sy - 1, sx - 1, ey + 0, false);
			drawLine(ex + 0, sy - 1, ex + 0, ey + 0, false);
			drawLine(sx - 0, sy - 1, ex + 0, sy - 1, false);
			drawLine(sx - 1, ey + 0, ex + 1, ey + 0, false);
		
		else if (m_useSurroundingShadows = 2) then
		
			setAlpha(m_transparency * 0.33);
			drawLine(sx - 2, sy - 2, sx - 2, ey + 1, false);
			drawLine(ex + 1, sy - 2, ex + 1, ey + 1, false);
			drawLine(sx - 1, sy - 2, ex + 1, sy - 2, false);
			drawLine(sx - 2, ey + 1, ex + 2, ey + 1, false);
			setAlpha(m_transparency * 0.67);
			drawLine(sx - 1, sy - 1, sx - 1, ey + 0, false);
			drawLine(ex + 0, sy - 1, ex + 0, ey + 0, false);
			drawLine(sx - 0, sy - 1, ex + 0, sy - 1, false);
			drawLine(sx - 1, ey + 0, ex + 1, ey + 0, false);
		
		end if
	
	end method
	
	'// -------------------------------------------------------------------------------------------------------------
	'// Activate this gadget.
	'// -------------------------------------------------------------------------------------------------------------
	method activate()
	
		m_active = true;
	
	end method
	
	'// -------------------------------------------------------------------------------------------------------------
	'// Dectivate this gadget.
	'// -------------------------------------------------------------------------------------------------------------
	method deactivate()
	
		m_active = false;
	
	end method
	
	'// -------------------------------------------------------------------------------------------------------------
	'// Returns true if the mouse is hovering over this gadget.
	'// -------------------------------------------------------------------------------------------------------------
	method mouseHovering:byte()
	
		if (mouseX() < m_posX or mouseX() > m_posX + m_width ..
		or  mouseY() < m_posY or mouseY() > m_posY + m_height) ..
			return false;
		
		return true;
	
	end method
	
	'// -------------------------------------------------------------------------------------------------------------
	'// The name of this gadget.
	'// -------------------------------------------------------------------------------------------------------------
	field m_name:string;
	
	'// -------------------------------------------------------------------------------------------------------------
	'// The type of this gadget.
	'// -------------------------------------------------------------------------------------------------------------
	field m_type:short;
	
	'// -------------------------------------------------------------------------------------------------------------
	'// If this gadget allows for keyboard input, all writable input will be put here.
	'// -------------------------------------------------------------------------------------------------------------
	field m_input:string;
	
	'// -------------------------------------------------------------------------------------------------------------
	'// Determines whether or not this gadget is visible.
	'// -------------------------------------------------------------------------------------------------------------
	field m_visible:byte;
	
	'// -------------------------------------------------------------------------------------------------------------
	'// Determines whether or not this gadget is active.
	'// -------------------------------------------------------------------------------------------------------------
	field m_active:byte = true;
	
	'// -------------------------------------------------------------------------------------------------------------
	'// The transparency of this gadget. 1.0 is fully visible, while 0.0 is fully invisible.
	'// -------------------------------------------------------------------------------------------------------------
	field m_transparency:double = 1.0;
	
	'// -------------------------------------------------------------------------------------------------------------
	'// Set the color of the primitive of this gadget. These are drawn before any actual design is put on the gadget.
	'// It's basically the background color.
	'// -------------------------------------------------------------------------------------------------------------
	field m_primitiveR:byte = 128;
	field m_primitiveG:byte = 128;
	field m_primitiveB:byte = 128;
	
	'// -------------------------------------------------------------------------------------------------------------
	'// Flag that determines whether or not to draw a shadow around the gadget. Set to 1 for a larger shadow. Set to
	'// 2 for a smaller shadow. Set to 0 to turn off.
	'// -------------------------------------------------------------------------------------------------------------
	field m_useSurroundingShadows:byte = 0;
	
	'// -------------------------------------------------------------------------------------------------------------
	'// Position of the gadget.
	'// -------------------------------------------------------------------------------------------------------------
	field m_posX:double;
	field m_posY:double;
	
	'// -------------------------------------------------------------------------------------------------------------
	'// The dimensions of the gadget.
	'// -------------------------------------------------------------------------------------------------------------
	field m_width:double;
	field m_height:double;
	
	'// -------------------------------------------------------------------------------------------------------------
	'// The name of the method that is going to be invoked when this button is pressed.
	'// -------------------------------------------------------------------------------------------------------------
	field m_methodHook:string;
	
	'// -------------------------------------------------------------------------------------------------------------
	'// The name of the object where the above method is found.
	'// -------------------------------------------------------------------------------------------------------------
	field m_hookedObject:object;
	
	'// -------------------------------------------------------------------------------------------------------------
	'// Pointer to the links in the gadget lists of the layer object this gadget resides in.
	'// -------------------------------------------------------------------------------------------------------------
	field m_gadgetListLink:TLink;
	field m_gadgetListReversedLink:TLink;
	
	'// -------------------------------------------------------------------------------------------------------------
	'// Pointer to the layer that contains this gadget.
	'// -------------------------------------------------------------------------------------------------------------
	field m_layer:object;

end type
